import router from '@/router';
import type {RouteLocationNormalizedLoaded} from 'vue-router';
import {getRawRoute} from '@/utils/routerHelper';
import {defineStore} from 'pinia';
import {store} from '@/store';
import {findIndex} from '@/utils';

export interface TagsViewState {
    visitedViews: RouteLocationNormalizedLoaded[];
    cachedViews: Set<string>;
}

export const useTagsViewStore = defineStore('tagsView', {
    state: (): TagsViewState => ({
        visitedViews: [],
        cachedViews: new Set(),
    }),
    getters: {
        getVisitedViews(): RouteLocationNormalizedLoaded[] {
            return this.visitedViews;
        },
        getCachedViews(): string[] {
            return Array.from(this.cachedViews);
        },
    },
    actions: {
        // 新增缓存和tag
        addView(view: RouteLocationNormalizedLoaded): void {
            this.addVisitedView(view);
            this.addCachedView();
        },
        // 新增tag
        addVisitedView(view: RouteLocationNormalizedLoaded) {
            if (this.visitedViews.some((v) => v.path === view.path)) return;
            if (view.meta?.noTagsView) return;
            this.visitedViews.push(
                Object.assign({}, view, {
                    title: view.meta?.title || 'no-name',
                }),
            );
        },
        // 新增缓存
        addCachedView() {
            const cacheMap: Set<string> = new Set();
            for (const v of this.visitedViews) {
                const item = getRawRoute(v);
                const needCache = !item.meta?.noCache;
                if (!needCache) {
                    continue;
                }
                const name = item.name as string;
                cacheMap.add(name);
            }
            if (Array.from(this.cachedViews).sort().toString() === Array.from(cacheMap).sort().toString())
                return;
            this.cachedViews = cacheMap;
        },
        // 删除某个
        delView(view: RouteLocationNormalizedLoaded) {
            this.delVisitedView(view);
            this.delCachedView();
        },
        // 删除tag
        delVisitedView(view: RouteLocationNormalizedLoaded) {
            for (const [i, v] of this.visitedViews.entries()) {
                if (v.path === view.path) {
                    this.visitedViews.splice(i, 1);
                    break;
                }
            }
        },
        // 删除缓存
        delCachedView() {
            const route = router.currentRoute.value;
            const index = findIndex<string>(this.getCachedViews, (v) => v === route.name);
            if (index > -1) {
                this.cachedViews.delete(this.getCachedViews[index]);
            }
        },
        // 删除所有缓存和tag
        delAllViews() {
            this.delAllVisitedViews();
            this.delCachedView();
        },
        // 删除所有tag
        delAllVisitedViews() {
            // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix)
            this.visitedViews = [];
        },
        // 删除其他
        delOthersViews(view: RouteLocationNormalizedLoaded) {
            this.delOthersVisitedViews(view);
            this.addCachedView();
        },
        // 删除其他tag
        delOthersVisitedViews(view: RouteLocationNormalizedLoaded) {
            this.visitedViews = this.visitedViews.filter((v) => {
                return v?.meta?.affix || v.path === view.path;
            });
        },
        // 删除左侧
        delLeftViews(view: RouteLocationNormalizedLoaded) {
            const index = findIndex<RouteLocationNormalizedLoaded>(
                this.visitedViews,
                (v) => v.path === view.path,
            );
            if (index > -1) {
                this.visitedViews = this.visitedViews.filter((v, i) => {
                    return v?.meta?.affix || v.path === view.path || i > index;
                });
                this.addCachedView();
            }
        },
        // 删除右侧
        delRightViews(view: RouteLocationNormalizedLoaded) {
            const index = findIndex<RouteLocationNormalizedLoaded>(
                this.visitedViews,
                (v) => v.path === view.path,
            );
            if (index > -1) {
                this.visitedViews = this.visitedViews.filter((v, i) => {
                    return v?.meta?.affix || v.path === view.path || i < index;
                });
                this.addCachedView();
            }
        },
        updateVisitedView(view: RouteLocationNormalizedLoaded) {
            for (let v of this.visitedViews) {
                if (v.path === view.path) {
                    v = Object.assign(v, view);
                    break;
                }
            }
        },
    },
});

export const useTagsViewStoreWithOut = () => {
    return useTagsViewStore(store);
};
